//! 交易模块 - 定义交易数据结构及签名验证逻辑

use ring::signature::Ed25519KeyPair; // 移除 , KeyPair};
use serde::{Serialize, Deserialize};
use hex;

/// 区块链交易结构
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Transaction {
    /// 发送方地址（公钥的十六进制字符串）
    pub sender: String,
    /// 接收方地址（公钥的十六进制字符串）
    pub receiver: String,
    /// 转账金额（无小数设计，单位：最小代币单位）
    pub amount: u64,
    /// 交易签名（发送方私钥对交易内容的签名）
    pub signature: Vec<u8>,
}

impl Transaction {
    /// 创建新交易（未签名状态）
    /// # 参数
    /// - sender: 发送方钱包地址  
    /// - receiver: 接收方钱包地址  
    /// - amount: 转账金额
    pub fn new(sender: String, receiver: String, amount: u64) -> Self {
        Transaction {
            sender,
            receiver,
            amount,
            signature: Vec::new(), // 初始无签名
        }
    }

    /// 使用钱包密钥对进行交易签名
    /// # 参数
    /// - key_pair: 发送方的Ed25519密钥对  
    /// # 注意
    /// 签名内容为交易消息的二进制数据，签名后存储到signature字段
    pub fn sign(&mut self, key_pair: &Ed25519KeyPair) {
        // 获取交易消息的二进制数据
        let message = self.get_message();
        // 使用私钥生成签名
        self.signature = key_pair.sign(message.as_ref())
            .as_ref()
            .to_vec();
    }

    /// 验证交易签名有效性
    /// # 返回
    /// bool: true表示签名有效，false表示无效或被篡改
    pub fn verify(&self) -> bool {
        // 解码发送方公钥（十六进制字符串转字节）
        let public_key_bytes = match hex::decode(&self.sender) {
            Ok(bytes) => bytes,
            Err(_) => return false, // 地址格式错误直接返回无效
        };
        
        // 创建未解析的公钥对象（使用ED25519算法）
        let public_key = ring::signature::UnparsedPublicKey::new(
            &ring::signature::ED25519, 
            &public_key_bytes
        );
        
        // 验证签名：公钥、原始消息、签名三者是否匹配
        public_key.verify(
            self.get_message().as_ref(), 
            self.signature.as_slice()
        ).is_ok() // 转换Result为bool
    }

    /// 生成交易签名消息（防篡改数据）
    /// 消息格式：发送方地址 + 接收方地址 + 金额（字符串拼接）
    /// 例如："addr1addr2100"
    pub fn get_message(&self) -> Vec<u8> {
        format!(
            "{}{}{}", 
            self.sender, 
            self.receiver, 
            self.amount
        ).into_bytes()
    }
}